# encoding: utf-8
"""
RESTful API pipelines resources
--------------------------
"""
import json
import logging

from flask_marshmallow import base_fields
from flask_restplus import Resource, fields

from app.extensions.api import Namespace, abort, http_exceptions
from app.modules.common import *
from app.modules.common.pipelines import PipelineNotFoundError
from flask_restplus_patched import Parameters
from app.modules.apps.models import App
from datetime import datetime
from app.extensions import db

log = logging.getLogger(__name__)  # pylint: disable=invalid-name
api = Namespace('pipelines', description = "The interface for pipelines operation.")

pipeline_schema = api.model('Pipeline', {
    'name': fields.String(required = True, description = 'The pipeline name'),
    'group': fields.String(required = True, description = 'The pipeline group'),
    'status': fields.String(required = True, description = 'The pipeline status'),
    'pip': fields.Integer(required = True, description = 'The pipeline pip'),
    'progress': fields.Integer(required = True, description = 'The pipeline progress'),
    'lasted_started': fields.DateTime(required = True, description = 'The pipeline lasted_started'),
    'lasted_finished': fields.DateTime(required = True, description = 'The pipeline lasted_finished'),
})

common_schema = api.model('result', {
    'success': fields.Boolean(required = True, description = 'Is Lock/free operation successfully.'),
    'msg': fields.String(required = False, description = 'Error message when lock/free failed.')
})


@api.route('/')
class Pipelines(Resource):
    """
    Manipulations with pipelines.
    """

    @api.marshal_with(pipeline_schema, as_list = True)
    def get(self):
        """
        List of pipelines.

        Returns a list of pipelines
        parameter.
        """

        return pipeline_manager.pipelines()


@api.route('/status')
class PipelinesStatus(Resource):
    """
    是否有pipline正在运行
    """

    @api.marshal_with(common_schema, as_list = False)
    def get(self):
        _list = pipeline_manager.pipelines()
        _status = False
        for _pip in _list:
            if _pip.status == 'RUNNING' or _pip.status == 'PENDING':
                _status = True
                break

        return {'success': _status, 'msg': ''}


@api.route('/<string:pipeline_name>')
@api.response(
    code = http_exceptions.NotFound.code,
    description = "Pipeline not found.",
)
class GetPipelineByName(Resource):
    """
    Manipulations with a specific pipeline.
    """

    @api.marshal_with(pipeline_schema)
    def get(self, pipeline_name):
        """
        Get a pipeline by Name.
        """
        return pipeline_manager.get_pipeline(pipeline_name)


class StartPipelineParameters(Parameters):
    pipeline_name = base_fields.String(
        description = 'The name of pipeline will be start',
        required = True
    )
    params = base_fields.String(
        description = 'The parameters of pipeline will be start,must be json format.',
        required = False,
        missing = "{}"
    )


@api.route('/start')
@api.response(
    code = http_exceptions.NotFound.code,
    description = "pipeline not found.",
)
class StartPipelineByName(Resource):
    """
    Manipulations with a specific pipeline.
    """

    @api.parameters(StartPipelineParameters())
    @api.marshal_with(pipeline_schema)
    def get(self, args):
        """
        Start a pipeline by name.
        """
        try:
            pipeline_name = args['pipeline_name']
            params = json.loads(args['params'])
            pipeline_manager.start_pipeline(pipeline_name = pipeline_name, pipeline_params = params)
            # 应用启动停止pipline，更新app字段
            _appid = str(pipeline_name).split('_')[0]
            _app = App.query.filter_by(app_id = _appid).first()
            if _app is None:
                return None
            if '_restart' in pipeline_name or '_install' in pipeline_name:
                _app.app_start_date = datetime.now()
                db.session.commit()
            elif '_stop' in pipeline_name:
                _app.app_stop_date = datetime.now()
                db.session.commit()

        except PipelineNotFoundError:
            abort(code = http_exceptions.NotFound.code, message = "Could not found the pipeline:%s" % pipeline_name)
        return None


pipeline_engine_status_schema = api.model('Pipeline_engine_status', {
    'watch_return_queue_thread_status': fields.Boolean(required = True,
                                                       description = 'The watch_return_queue_thread_status'),
})


@api.route('/get_watch_return_queue_thread_status')
class get_watch_return_queue_thread_status(Resource):
    @api.marshal_with(pipeline_engine_status_schema)
    def get(self):
        """
        List of pipelines.

        Returns a list of pipelines
        parameter.
        """
        return pipeline_manager.get_watch_return_queue_thread_status()


@api.route('/restart_watch_return_queue_thread_status')
class restart_watch_return_queue_thread_status(Resource):
    @api.marshal_with(pipeline_engine_status_schema)
    def get(self):
        """
        List of pipelines.

        Returns a list of pipelines
        parameter.
        """
        pipeline_manager.restart_watch_return_queue_thread_status()
        return pipeline_manager.get_watch_return_queue_thread_status()
